import {
    ol,
    layerConfigDefautls,
    projzh
} from '../constants'

const objectAssign = require('object-assign');
class BaseLayers {





    /**
     * 获取版权信息
     * @returns {Xr.Attribution|Jr.Attribution|Wr.Attribution|*|ol.Attribution|ol.control.Attribution}
     * @private
     */
    _getAttribution(params) {

        let attribution
        if (params === true) {
            params = {}
            params['url'] = config.INDEX_URL
            params['messages'] = 'contributors.'
            params['title'] = 'GMap'
            attribution = new ol.Attribution({
                html: '&copy; ' + '<a href="' + params['url'] + '">' + params['title'] + '</a> ' + params['messages']
            })
        } else if (typeof params === 'object') {
            attribution = new ol.Attribution({
                html: '&copy; ' + '<a href="' + params['url'] + '">' + params['title'] + '</a> ' + params['messages']
            })
        }
        return attribution
    }


    addBaseLayers(params) {
        let options = params || [];



        if (!options || !Array.isArray(options) || options.length <= 0) {

            return [new ol.layer.Group({
                layers: [this._getLayer({
                    layerName: 'AMap_online',
                    layerType: 'AMap_online',
                    tileType: 0,
                    isVisible: true,
                    isDefault: true,
                    isBaseLayer: true,
                    attribution: {
                        url: 'http://www.keepsoft.net/',
                        title: '贵仁科技',
                        messages: '版权所有'
                    }

                })],
                isBaseLayer: true
            })]

        } else {
            return [new ol.layer.Group({
                layers: this._getBaseLayerGroup(params)

            })]
        }
    }


    /**
     * 获取图层组
     * @returns {ol.layer.Group}
     */
    _getBaseLayerGroup(layerConfig) {

        let layers = [];
        if (layerConfig && Array.isArray(layerConfig) && layerConfig.length > 0) {
            layerConfig.forEach(config => {
                if (config['layerName'] && config['layerType']) {
                    let options = objectAssign({}, layerConfigDefautls, config);

                    let layer = this._getLayer(options);
                    if (layer) layers.push(layer);

                }
            })
        }
        
        return layers;
    }

    /**
     * 获取图层
     * @param layerConfig
     * @returns {*}
     * @private
     */
    _getLayer(layerConfig) {
        let layer;
        switch (layerConfig['layerType']) {

            case 'AMap_online':
                layer = this._getAMapLayer_online(layerConfig)
                break;
            case 'TianDiMap_online':
                layer = this._getTianDiLayer_online(layerConfig)
                break;
            case 'BaiDu_online':
                layer = this._getBaiDuLayer_online(layerConfig)
                break;
            case 'GoogleMap_online':
                layer = this._getGoogleLayer_online(layerConfig)
                break;
            case 'AMap_offline':
                layer = this._getAMapLayer_offline(layerConfig)
                break;
            case 'GoogleMap_offline':
                layer = this._getGoogleLayer_offline(layerConfig)
                break;
            // case 'BaiDu_offline':
            //     layer = this._getBaiDuLayer_offline(layerConfig)
            //     break;            
            case 'geojson':
                layer = this._getGeoJson(layerConfig);
                break;
            case 'kljson':
                layer = this._getKlJson(layerConfig);
                break;
            case 'wms':
                layer = this._getImageWMSLayer(layerConfig);
                break;
            case 'Arcgis_offline':
                layer = this._getArcGisLayer_offline(layerConfig);
                break;
            case 'ArcGis_server':
                layer = this._getAArcGis_server(layerConfig);
                break;
            default:
                throw new Error('不支持的图层类型！')
        }
        layer = this._addLayerAlias(layer, layerConfig)
       
        return layer;
    }


    /**
     * 添加底图标识
     * @param layer
     * @param layerConfig
     * @returns {*}
     * @private
     */
    _addLayerAlias(layer, layerConfig) {
        const isDefault = (layerConfig['isDefault'] === true) ? layerConfig['isDefault'] : false
        layer.set('isDefault', isDefault)
        layer.set('isBaseLayer', true)
        layer.setVisible(isDefault)
        layerConfig.viewonly && layer.set('viewonly',true);
        layerConfig.hidden && layer.setVisible(false);
        if (this.isHasAttribution === 0) {
            layer.getSource().setAttributions(this._getAttribution(layerConfig['attribution']))
            this.isHasAttribution = 1
        }

        return layer
    }

    /**
     *
     * 获取在线高德地图底图
     * @param  config
     * @returns {ol.layer.Tile}
     */
    _getAMapLayer_online(options) {

        let url;
        switch (options['tileType']) {
            case 0:
                url = "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7";
                break;
            case 1:
                url = "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=2&style=7";
                break;
            case 2:
                url = "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=6";
                break;
            case 3:
                url = "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=8";
                break;
            case 4:
                url = "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=2&style=8";
                break;
        }
        let _options = objectAssign({}, {
            source: new ol.source.XYZ({
                projection: ol.proj.get('EPSG:3857'),
                wrapX: true,
                opaque: (options['opaque'] === true) ? true : false, // 图层是否不透明（主题相关）
                url: url,
                crossOrigin: 'Anonymous'
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;
    }

/**
     *
     * 获取离线高德地图底图
     * @param  config
     * @returns {ol.layer.Tile}
     */
    _getAMapLayer_offline(options) {
        let url;
        let _options = objectAssig({}, {
            source: new ol.source.XYZ({
                url: options['url']
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;
    }

    /**
     *
     *获取在线天地图底图
     * @param {any} config
     * @memberof BaseLayers
     */
    _getTianDiLayer_online(options) {

        let url;
        switch (options['tileType']) {
            case 0:
                url = "http://t{0-4}.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}";
                break;
            case 1:
                url = "http://t{0-4}.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}";
                break;
            case 2:
                url = "http://t{0-4}.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}";
                break;
            case 3:
                url = "http://t{0-4}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}";
                break;



        }

        let _options = objectAssign({}, {
            source: new ol.source.XYZ({
                projection: ol.proj.get('EPSG:3857'),
                wrapX: true,
                opaque: (options['opaque'] === true) ? true : false, // 图层是否不透明（主题相关）
                url: url,
                crossOrigin: 'Anonymous',
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;
    }

    /**
     *
     * 获取在线百度地图
     * @param {any} config
     * @memberof BaseLayers
     */
    _getBaiDuLayer_online(options) {
        let extent = [72.004, 0.8293, 137.8347, 55.8271];
        //定义百度坐标
        //地址：https://github.com/openlayers/openlayers/issues/3522
        let baiduMercator = new ol.proj.Projection({
            code: 'baidu',
            extent: ol.extent.applyTransform(extent, projzh.ll2bmerc),
            units: 'm'
        });
        ol.proj.addProjection(baiduMercator);
        ol.proj.addCoordinateTransforms('EPSG:4326', baiduMercator, projzh.ll2bmerc, projzh.bmerc2ll);
        ol.proj.addCoordinateTransforms('EPSG:3857', baiduMercator, projzh.smerc2bmerc, projzh.bmerc2smerc);
        let resolutions = [];
        for (let i = 0; i < 19; i++) {
            resolutions[i] = Math.pow(2, 18 - i);
        }
        let tilegrid = new ol.tilegrid.TileGrid({
            origin: [0, 0],
            resolutions: resolutions,
            extent: ol.extent.applyTransform(extent, projzh.ll2bmerc),
            tileSize: [256, 256]
        });

        let satUrls = [0, 1, 2, 3, 4].map(function (sub) {
            return 'http://shangetu' + sub +
                '.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46&udt=20150601';
        });
        let urls = [0, 1, 2, 3, 4].map(function (sub) {
            return 'http://online' + sub +
                '.map.bdimg.com/onlinelabel/qt=tile&x={x}&y={y}&z={z}&v=009&styles=pl&udt=20170301&scaler=1&p=1';
        });
        let _options = objectAssign({}, {
            source: new ol.source.TileImage({
                projection: 'baidu',
                tileGrid: tilegrid,
                tileUrlFunction: function (tileCoord, pixelRatio, proj) {

                    if (!tileCoord) return "";
                    let z = tileCoord[0];
                    let x = tileCoord[1];
                    let y = tileCoord[2];
                    let hash = (x << z) + y;
                    let index = hash % urls.length;
                    index = index < 0 ? index + urls.length : index;
                    if (options['tileType'] == 1) {

                        return satUrls[index].replace('{x}', x).replace('{y}', y).replace('{z}', z);
                    } else {
                        return urls[index].replace('{x}', x).replace('{y}', y).replace('{z}', z);
                    }
                },
                crossOrigin: 'Anonymous'
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;

    }

    /**
     *
     * 获取离线百度地图 --有偏移  未完成
     * @param {any} config
     * @memberof BaseLayers
     */
    _getBaiDuLayer_offline(options) {
        // 自定义分辨率和瓦片坐标系
        var resolutions = [];
        var maxZoom = 18;

        // 计算百度使用的分辨率
        for (var i = 0; i <= maxZoom; i++) {
            resolutions[i] = Math.pow(2, maxZoom - i);
        }
        var tilegrid = new ol.tilegrid.TileGrid({
            origin: [0, 0],
            resolutions: resolutions    // 设置分辨率
        });

        let _options = objectAssign({}, {
            source: new ol.source.TileImage({
                projection: 'EPSG:3857',
                tileGrid: tilegrid,
                tileUrlFunction: function (tileCoord, pixelRatio, proj) {
                    var z = tileCoord[0];
                    var x = tileCoord[1];
                    var y = tileCoord[2];

                    // 百度瓦片服务url将负数使用M前缀来标识
                    if (x < 0) {
                        x = -x;
                    }
                    if (y < 0) {
                        y = -y;
                    }
                    return ""+options['url']+"/" + z + "/" + x + "/" + y + ".jpg";
                }
            })
        }, options);
       
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;

    }
    /**
     *
     * 获取在线谷歌地图
     * @param {any} options
     * @memberof BaseLayers
     */
    _getGoogleLayer_online(options) {
        let url;
        switch (options['tileType']) {
            case 0:
                url = 'http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i345013117!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0';
                break;
            case 1:
                url = 'http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i380072576!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmapSatellite!4e0!5m1!1e0';
                break;
            case 2:
                url = 'http://mt1.google.cn/maps/vt?lyrs=s%40742&hl=zh-Hans-CN&gl=CN&x={x}&y={y}&z={z}';
                break;
            case 3:
                url = 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e4!2st!3i393!2m3!1e0!2sr!3i393087804!3m12!2szh-Hans-CN!3sCN!5e78!12m4!1e68!2m2!1sset!2sTerrain!12m3!1e37!2m1!1ssmartmaps!4e0!5m1!5f2';
                break;
            case 4:
                url= 'http://mt1.google.cn/vt/lyrs=s@131,r@240000000&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}&s=Gali';
                break;
        }
        let _options = objectAssign({}, {
            source: new ol.source.XYZ({
               //crossOrigin:'anonymous',
					crossOrigin:'*',
                url: url
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;


    }

    /**
     *
     * 获取离线谷歌地图
     * @param {any} options
     * @memberof BaseLayers
     */
    _getGoogleLayer_offline(options) {
        let _options = objectAssign({}, {
            source: new ol.source.XYZ({
            url: options['url']
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;

    }

    /**
     * 获取arcgis切片
     */
    _getArcGisLayer_offline(options) {
        var _this = this;
        let _options = objectAssign({}, {
            source: new ol.source.XYZ({
                tileUrlFunction: function(tileCoord){
                      var x = 'C' + _this.zeroPad(tileCoord[1], 8, 16);
                      var y = 'R' + _this.zeroPad(-tileCoord[2] - 1, 8, 16);
                      var z = 'L' + _this.zeroPad(tileCoord[0], 2, 10);
                      var png = options['url'] + z + '/' + y + '/' + x + '.png'; // 'tilemap/bhxq/Layers/_alllayers/'
                      return png;
                    },
                    projection: 'EPSG:3857'
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;
    }

    _getAArcGis_server(options){
        let _options = objectAssign({}, {
			//extent:config.option.extent,
            source: new ol.source.TileArcGISRest({
          		url: options.url
            })
        }, options);
        let baseLayer = new ol.layer.Tile(_options);
        return baseLayer;
    }

    zeroPad(num, len, radix){
		var str = num.toString(radix || 10);
        while (str.length < len){
          str = "0" + str;
        }
        return str;
	}

    /**
     *
     * geojson
     * @param {any} options
     * @memberof BaseLayers
     */
    _getGeoJson(options) {

        if (!options['url']) {
            throw new Error('geojson url 不能为空')
        }

        let vectorSource = new ol.source.Vector({
            url: options['url'],
            format: new ol.format.GeoJSON()
        });

        let _options = objectAssign({}, {
            source: vectorSource,
            crossOrigin: 'Anonymous',
        }, options);

        let vectorLayer = new ol.layer.Vector(_options);
        return vectorLayer;
    }

    /**
     *
     * kljson
     * @param {any} options
     * @memberof BaseLayers
     */
    _getKlJson(options) {
        var _this = this;
        var klData = {};
        if (typeof ($) == 'undefined') {
            throw new Error('依赖jquery,请引用jquery')
        }
        if (!options['url'] && !options['isDynamic']) {
            throw new Error('kljson url 不能为空')
        }
        let styleFun = function (feature) {
            let prop = feature.getProperties();
            let items = klData.items;
            let item = items[0];
            let style = item.style;
            let field = klData.field;
            var b =  klData.breaks;
            var type =  klData.type;
            if (feature.get('_hidden')) return null;
            let polygonStyle = null;
            switch(type){
             case 'break':  //处理三角网格的kljson
                    for(var i=0;i<b.length;i++){
                        let item = items[i];
                        let style = item.style;
                        if(prop[field]<=b[i]){
                            polygonStyle=new ol.style.Style({
                                stroke: new ol.style.Stroke(style['stroke']),
                                fill: new ol.style.Fill(style['fill'])
                            });
                            break;
                        }
                    }
                    if(prop[field]>b[b.length-1/*i*/]){
                        let style = items[items.length-1].style;
                        polygonStyle=new ol.style.Style({
                            stroke: new ol.style.Stroke(style['stroke']),
                            fill: new ol.style.Fill(style['fill'])
                        });  
                    } 
                    break;
            case 'single': //只有单个样式
                    let image;
                    if(style['image'] && style['image']["xt"]=="circle"){
                         image = new ol.style.Circle({
                            radius: (style["image"]['radius']),
                            fill: new ol.style.Fill(style["image"]['fill']),
                            // radius:4,
                            // fill: null,
                            stroke: new ol.style.Stroke({color: 'red', width: 1})
                        });
                        polygonStyle =  new ol.style.Style({
                            image: image
                          })
                    }else{
                        if(style['fill']){
                            polygonStyle=new ol.style.Style({
                                stroke: new ol.style.Stroke(style['stroke']),
                                fill: new ol.style.Fill(style['fill'])
                            });
                        }else{
                            polygonStyle=new ol.style.Style({
                                stroke: new ol.style.Stroke(style['stroke'])
                             });
                        }
                    }
                     
                    break;
                   
            case 'icon':
                // if(items.length == 1){
                //     polygonStyle = new ol.style.Style({
                //         image: new ol.style.Icon({
                //             src: style.image.src
                //             })
                //         });
                // }else{
                    for(var i=0;i<items.length;i++){
                        let item = items[i];
                        let style = item.style;
                        let imageStyle = style.image;
                        if(prop["type"]==item["type"]){
                            polygonStyle = new ol.style.Style({
                                image: new ol.style.Icon({
                                    src: imageStyle.src,
                                    scale:imageStyle.scale
                                   // ,anchor : [imageStyle.anchor[0],imageStyle.anchor[1]]
                                    })
                                });
                                break;
                        }
                       
                    } 
                // }
                break; 
             default:
                    for (let i = 0; i < items.length; i++) {
                        let item = items[i];
                        
                        if (item.value == prop[field]) {
                            let style = item.style;
                            // console.log(_this.json2obj(style,'style'))
                            polygonStyle = new ol.style.Style({
                                stroke: new ol.style.Stroke(style['stroke']),
                                fill: new ol.style.Fill(style['fill'])
                            })
                            break;

                        }
                    }
            break;       
                }
            return polygonStyle;



        }
        let _options = objectAssign({}, {
            // crossOrigin: 'Anonymous',
					crossOrigin:'*',
            style: styleFun

        }, options);
        let vectorLayer = new ol.layer.Vector(_options);
        $.ajaxSettings.async = false;
        //调用使用
    //    $.ajax({
    //         url: options['url'],
    //         datatype: "json",
    //         type: 'get',
    //         success: function (data) {
    //         //成功后回调
    //         // alert("回调函数成功了");
    //         var data = JSON.parse(data);
    //         let vectorSource = new ol.source.Vector();
    //         let geo = data.geodata;
    //         klData = data.style;
    //         let type = data.type;
    //         if(geo) {
    //         if (geo.type == "Topology") {
    //         vectorSource.addFeatures((new ol.format.TopoJSON()).readFeatures(geo));
    //         } else if (geo.type) {
    //         vectorSource.addFeatures((new ol.format.GeoJSON()).readFeatures(geo));
    //         }
    //         }
    //         vectorLayer.setSource(vectorSource);
    //         },
    //         error: function(e){
    //         //失败后回调
    //         //alert("服务器请求失败");
    //         },
    //         beforeSend: function(){
    //         //发送请求前调用，可以放一些"正在加载"之类额话
    //         //alert("正在加载");
    //     }})
    options['url'] && $.getJSON(options['url'], function (data) {
            let vectorSource = new ol.source.Vector();
            let geo = data.geodata;
            klData = data.style;
            let type = data.type;
            if(geo){
                if (geo.type == "Topology") {
                    vectorSource.addFeatures((new ol.format.TopoJSON()).readFeatures(geo));
                } else if (geo.type) {
                    vectorSource.addFeatures((new ol.format.GeoJSON()).readFeatures(geo));
                }
            }
            vectorLayer.setSource(vectorSource);
        })

        return vectorLayer;
    }

	
	upfchar(xt){
        return xt.substr(0,1).toUpperCase()+xt.substring(1);
    }

	json2obj (json, prop){

     this.clzzMap = {
	    'fill':'ol.style.Fill',
	    'text':'ol.style.Text',
	    'circle':'ol.style.Circle',
	    'stroke':'ol.style.Stroke',
	    'icon':'ol.style.Icon'
	};
	    if(!json) return null;
	    var obj=this.clone(json);
	    var clzz=this.clzzMap[prop];
	    if(!clzz){
    	    if(obj.xt){
    	        clzz=this.clzzMap[obj.xt];
    	        if(!clzz)
    	            clzz='ol.'+prop+'.'+this.upfchar(obj.xt);
    	    }else{
    	        clzz='ol.'+prop+'.'+this.upfchar(prop);
    	    }
	    }
	    $.each(obj,function(value,key,self){
	        //console.log(arguments);
	        if(typeof(value)=='object' && !Array.isArray(value)){
	            self[key]=this.json2obj(value,key);
	        }
	        console.log(key); console.log(value);
	    },this);
	    console.log(clzz); console.log(obj);
	    return objectAssign({},clzz,obj);
	}

     clone(obj) {
        var o;
        if (typeof obj == "object") {
            if (obj === null) {
                o = null;
            } else {
                if (obj instanceof Array) {
                    o = [];
                    for (var i = 0, len = obj.length; i < len; i++) {
                        o.push(clone(obj[i]));
                    }
                } else {
                    o = {};
                    for (var j in obj) {
                        o[j] = this.clone(obj[j]);
                    }
                }
            }
        } else {
            o = obj;
        }
        return o;
    }

    /**
     * Images WMS 方式加载
     * @param layerConfig
     * @private
     */
    _getImageWMSLayer(layerConfig) {
        let layerName = layerConfig['layerName'] || ''
        layerConfig['addLayer'] = false
        layerConfig['create'] = true
        let layer = this.createImageWMSLayer(layerName, layerConfig)
        return layer
    }

    //与MapTool配合使用，可移植到其他页面，并作为临时图层
    crtLayer(){
		var sourceM = this._sourceM = new ol.source.Vector({ wrapX: false });
	    var layerM = this._layerM = new ol.layer.Vector({
	    	id: 'measureLayer',
	        source: sourceM,
	        style: new ol.style.Style({
	          fill: new ol.style.Fill({
	            color: 'rgba(255, 255, 255, 0.2)'
	          }),
	          stroke: new ol.style.Stroke({
	            color: '#ffcc33',
	            width: 2
	          }),
	          image: new ol.style.Circle({
	            radius: 7,
	            fill: new ol.style.Fill({
	              color: '#ffcc33'
	            })
	          })
	        })
	      });
	    layerM.setZIndex(122);
	    this.map.addLayer(layerM);
	    
	    var sourceMarker = this._sourceMa = new ol.source.Vector({ wrapX: false });
	    var layerMarker = this._layerMa = new ol.layer.Vector({
	    	id: 'markLayer',
	        source: sourceMarker,
	        style: new ol.style.Style({
	          fill: new ol.style.Fill({
	            color: 'rgba(255, 255, 255, 0.2)'
	          }),
	          stroke: new ol.style.Stroke({
	            color: '#ffcc33',
	            width: 2
	          }),
	        //   image: new ol.style.Icon({
		    //       src: 'js/app/frmwk/gis/images/marker.png'
		    //     })
	        })
	      });
	    layerMarker.setZIndex(222);
	    this.map.addLayer(layerMarker);
	}
	

}


export default BaseLayers